#include "ggraphtable.h"

GGraphTable::GGraphTable(QWidget *parent) :
    QWidget(parent), translateVector(QPoint()), showTree(false)
{
    setMinimumSize(500,500);
    setBaseSize(500,500);
    setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    setMouseTracking(true);
}

void GGraphTable::setGraph(const Graph& g)
{
    graph = g;

    resetGraph();

    for (unsigned int i = 0;i<graph.getSize();++i)
    {
        if (graph[i].data!=INT_MIN)
        {
            GNode *node=new GNode(this);
            node->setFixedSize(50,50);
            node->graphNode=&graph[i];
            node->show();
            nodes.push_back(node);
        }
    }

    initNodesPos(0.1,0.1);
}

const Graph& GGraphTable::getGraph() const
{
    return this->graph;
}

void GGraphTable::resetGraph()
{
    for (int i=0;i<nodes.size();++i)
    {
        delete nodes[i];
    }
    nodes.clear();
}

void GGraphTable::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);

    painter.translate(translateVector);

    painter.setRenderHint(QPainter::Antialiasing);

    double angle = 0.34906585039886591538473815369772/2;

    for (int i = 0; i<nodes.size();++i)
    {
        if (!showTree || (showTree && nodes[i]->isProcessed))
        {
            Graph_Node *p = nodes[i]->graphNode->next;
            while (p)
            {
                QPointF end = (QPointF)(nodes[graph.getIndexOf(*p)]->pos()+ QPoint(25,25));
                QPointF start=(nodes[i]->pos() + QPoint(25,25));

                if (nodes[i]->isProcessed)
                {
                    QPen pen(QBrush(Qt::red), 1.5);
                    painter.setPen(pen);
                }
                else
                {
                    QPen pen(QBrush(Qt::black), 1.5);
                    painter.setPen(pen);
                }

                QPointF direction=(QPointF)(end - start);
                double length = qSqrt(qPow(direction.x(),2)+qPow(direction.y(),2));
                if (length!=0)
                    direction/=length;

                QPointF temp=QPointF(direction.x()*cos(angle)-direction.y()*sin(angle),
                                     direction.x()*sin(angle)+direction.y()*cos(angle));


                painter.drawLine(end-17.5*direction,end-40.0f*temp);

                temp=QPointF(direction.x()*cos(-angle)-direction.y()*sin(-angle),
                                                 direction.x()*sin(-angle)+direction.y()*cos(-angle));

                painter.drawLine(end-17.5*direction,end-40.0f*temp);

                painter.drawLine(
                        start,
                        end
                        );
                p = p->next;
            }
        }
    }
    QWidget::paintEvent(e);
}

void GGraphTable::initNodesPos(double spring, double damping, double charge)
{
    for (int i = 0;i<nodes.size();++i)
    {
        nodes[i]->velocity=QPointF(0,0);
        nodes[i]->move(qrand()%(int)(width()*0.9),qrand()%(int)(height()*0.9));
    }
}

QPointF GGraphTable::Coulomb_Law(const GNode &a, const GNode &b) const
{
    double k = 10E5;
    QPointF F = QPointF();

    QPointF direction=a.pos()-b.pos();

    double r = qSqrt(direction.x() * direction.x()+
                     direction.y() * direction.y());

    QPointF norm=direction/r;

    F=(k/(r*r))*norm;
    return F;
}

QPointF GGraphTable::Hooke_Law(const QPointF &a, const double& spring) const
{
    QPointF F=QPointF();
    F= - spring * a;
    return F;
}

void GGraphTable::mouseMoveEvent(QMouseEvent *e)
{
    this->setCursor(Qt::ArrowCursor);
    int i=0;
    while (i<nodes.size() && !nodes[i]->isSelected)
    {
        ++i;
    }
    if (i<nodes.size())
    {
        QSize size=nodes[i]->size()/2;
        nodes[i]->move(e->pos()-QPoint(size.width(),size.height()));
        update();
    }
}

void GGraphTable::setShowTree(const bool &value)
{
    showTree=value;
    update();
}
